package ing.gzq.service;

import ing.gzq.base.Result;
import ing.gzq.base.ResultCache;
import ing.gzq.dao.CourseDao;
import ing.gzq.model.*;
import ing.gzq.websocket.WebsocketSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import static ing.gzq.base.ResultCache.getDataOk;
import static ing.gzq.base.ResultCache.getFailureDetail;
import static ing.gzq.base.ResultCache.getPermissionDeniedDetail;
import static ing.gzq.model.Message.*;
import static ing.gzq.service.AuthenticationService.getUserInSecurityContext;

/**
 * Created by gzq on 17-7-20.
 */
@Service
public class CourseService {

    @Autowired
    CourseDao courseDao;

    @Autowired
    AuthenticationService authService;


    @Autowired
    WebsocketSupport websocketSupport;

    public Result insertCourse(Course course) {
        try {
            courseDao.insertCourse(course);
            return ResultCache.getDataOk(
                    Collections.singletonMap("courseId",course.getId()));
        } catch (Exception e) {
            e.printStackTrace();
            return getFailureDetail("插入课程失败");
        }
    }

    public Result getCourseByTeacherId(String teacherId) {
        List<Course> courseList = courseDao.getCourseByTeacherId(teacherId);
        return ResultCache.getDataOk(courseList);
    }

    public Result getCourseByStudentId(String studentId) {
        List<Course> courseList = courseDao.getCourseByStudentId(studentId);
        return ResultCache.getDataOk(courseList);
    }

    public Result getCourseById(Long courseId) {
        Course course = courseDao.getCourseById(courseId);
        if (course == null) {
            return getFailureDetail("课程不存在");
        }
        return ResultCache.getDataOk(course);
    }

    public Result getAllCourse() {
        List<Course> courseList = courseDao.getAllCourse();
        return ResultCache.getDataOk(courseList);
    }


    public Result startCourse(final long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");

        Course course = courseDao.getCourseById(courseId);
        course.setState(true);

        return modifyCourseState(course);
    }

    @Transactional
    public Result endCourse(final long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");
        Course course = courseDao.getCourseById(courseId);
        course.setState(false);
        return modifyCourseState(course);
    }

    public Result search(String keyWord) {
        List<Course> courseList = courseDao.search("%" + keyWord + "%");
        return ResultCache.getDataOk(courseList);
    }

    public Result joinCourse(Long courseId) {
        try {
            User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            courseDao.insertStudentToCourse(courseId, user.getUsername());
            return ResultCache.OK;
        } catch (Exception e) {
            e.printStackTrace();
            return getFailureDetail(e.getMessage());
        }
    }

    public Result quitCourse(Long courseId) {
        User user = getUserInSecurityContext();
        if(!authService.checkIfInCourse(courseId))
            return getFailureDetail("not in the course");
        try {
            courseDao.deleteStudent(courseId, user.getUsername());
            return ResultCache.OK;
        } catch (Exception e) {
            e.printStackTrace();
            return getFailureDetail(e.getMessage());
        }
    }

    public Result modifyCourseIntroduce(Course course) {
        if(!authService.checkIfInCourse(course.getId()))
            return getPermissionDeniedDetail("not in the course");
        try {
            courseDao.modifyCourseIntroduce(course);
            return ResultCache.OK;
        } catch (Exception ex) {
            ex.printStackTrace();
            return getFailureDetail(ex.getMessage());
        }
    }

    public Result getAllJoinedStudent(Long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");

        List<StudentInfo> students = courseDao.getStudentsByCourseId(courseId);
        return ResultCache.getDataOk(students);
    }

    public Result deleteMember(Long courseId, String studentId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");

        try {
            courseDao.deleteStudent(courseId, studentId);
            return ResultCache.OK;
        } catch (Exception e) {
            e.printStackTrace();
            return getFailureDetail(e.getMessage());
        }
    }



    public Result sign(Long courseId) {
        Course course = courseDao.getCourseById(courseId);
        if(course == null)
            return getFailureDetail("course is not exist");
        if(!course.getState())
            return getFailureDetail("course not start");
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");

        try {

            User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

            if(checkSignedToday(courseId,user.getUsername())){
                return ResultCache.OK;
            }

            courseDao.sign(courseId, user.getUsername());

            Message<String> message = new Message<>(NEW_CHECK_IN);
            message.setName(user.getUsername());
            message.setData(user.getName());

            websocketSupport.sendMessageToTeacher(courseId, message);

            return ResultCache.OK;
        } catch (Exception e) {
            e.printStackTrace();
            return getFailureDetail(e.getMessage());
        }
    }

    private boolean checkSignedToday(Long courseId, String studentId) {
        int count = courseDao.checkSignedToday(courseId,studentId);
        return count >0 ? true : false;
    }


    public Result startLive(Long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");

        Course course = courseDao.getCourseById(courseId);
        course.setLive(true);
        return modifyCourseStateAndNotice(course,OPEN_LIVE_MESSAGE);
    }

    public Result endLive(Long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");

        Course course = courseDao.getCourseById(courseId);
        course.setLive(false);
        return modifyCourseStateAndNotice(course,CLOSE_LIVE_MESSAGE);
    }


    public Result openChat(final Long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");

        Course course = courseDao.getCourseById(courseId);
        course.setChat(true);
        return modifyCourseStateAndNotice(course,OPEN_CHAT_MESSAGE);
    }

    public Result closeChat(Long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");

        Course course = courseDao.getCourseById(courseId);
        course.setChat(false);
        return modifyCourseStateAndNotice(course,CLOSE_CHAT_MESSAGE);
    }


    private Result modifyCourseState(Course course ) {
        try {
            courseDao.modifyCourseState(course);
            return ResultCache.OK;
        } catch (Exception e) {
            e.printStackTrace();
            return getFailureDetail(e.getMessage());
        }
    }

    private Result modifyCourseStateAndNotice(Course course,Message<String> message) {
        try {
            courseDao.modifyCourseState(course);
            websocketSupport.sendMessageToAll(course.getId(),message);
            return ResultCache.OK;
        } catch (Exception e) {
            e.printStackTrace();
            return getFailureDetail(e.getMessage());
        }
    }

    public Result getSignedStudents(Long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in the course");
        List<StudentInfo> studentInfos = courseDao.getAllSignedStudent(courseId);
        return getDataOk(studentInfos);
    }
}
